package com.TeamJigsaw.DanteTrail.Models;

import java.util.ArrayList;
import java.util.List;

import com.TeamJigsaw.DanteTrail.Debug.Debug;

/**
 * Represents a party and performs various party responsibilities
 * @author David Chi
 *
 */
public class Party {
	private List<PartyMember> party;
	
	private Player player;
	
	private Wagon wagon;
	
	private int clothes;
	
	private int food;
	
	private int ammo;
	
	private int wheels;
	
	private int axels;
	
	private int tongues;
	
	private int pace;
	
	private int rations;
	
	private int money;
	
	private int weight;
	
	private final int MAX_WEIGHT;
	
	private int totalDistance;
	
	private int distanceLeft;
	
	//static contsants
	public static final int OKAY = 0;
	
	public static final int OUT_OF_FOOD = 1;
	
	public static final int REACHED_DEST = 2;
	
	public static final int REACHED_CP = 3;
	
	/**
	 * Creates and initializes the party with default names
	 */
	public Party() {
		party = new ArrayList<PartyMember>();
		clothes = 0;
		ammo = 0;
		wheels = 0;
		axels = 0;
		tongues = 0;
		player = null;
		money = 0; // How much money are we actually starting with? Right now, we can't actually buy anything.
		weight = 0;
		MAX_WEIGHT = 3500;
		totalDistance = 0;
		distanceLeft = 102;
		wagon = new Wagon();
	}
	
	/**
	 * Add a party member to the party
	 * @param newMember The new party member to be added
	 * @return Whether the operation was successful or not
	 */
	public boolean add(PartyMember newMember) {
		party.add(newMember);
		return false;
	}
	
	/**
	 * Removes all party members from the party
	 */
	public void clear() {
		party.clear();
	}
	
	/**
	 * Adds a player to the party 
	 * @param player The player to be added
	 * @return Whether or not the player was successfully added
	 */
	public boolean addPlayer(Player player) {
		if(player == null){
			return false;
		}
		this.player = player;
		return true;
	}
	
	/**
	 * Adds ammo to the party
	 * @param ammo The amount of ammo to be added
	 * @return Whether or not the ammo was successfully added
	 */
	public boolean addAmmo(int ammo){
		this.ammo += ammo;
		if(this.ammo < 0)
			this.ammo = 0;
		return true;
	}
	
	/**
	 * Adds food to the party
	 * @param food The amount of food to be added
	 * @return Whether or not the food was successfully added
	 */
	public boolean addFood(int food){
		Debug.println("In addFood(), BEFORE -5 food is added, the amount of food left is: " + this.food, Debug.M_TEN_DEMO);
		this.food = this.food + food;
		Debug.println("In addFood(), AFTER -5 food is added, the amount of food left is: " + this.food, Debug.M_TEN_DEMO);
		if (this.food < 0)
			this.food = 0;
		return true;
	}
	
	/**
	 * Adds clothes to the party
	 * @param clothes The amount of clothes to be added
	 * @return Whether or not the food was successfully added
	 */
	public boolean addClothes(int clothes){
		this.clothes += clothes;
		if(this.clothes < 0)
			this.clothes = 0;
		return true;
	}
	
	/**
	 * Gets and returns the player in the party
	 * @return The player in the party
	 */
	public Player getPlayer() {
		return player;
	}
	
	/**
	 * Steps through a single cycle of party movement
	 * @return Whether or not the step operation was successful or not
	 */
	public int step(int pace, int rationRate, List<Checkpoint> checkpoints){
		List<PartyMember> partyMembers = party;
		int sum = 1;
		for (int i = 0; i < partyMembers.size(); i++){
			int status = partyMembers.get(i).getStatus();
			if (status == 0){
				sum++;
			}
		}
		int ration = rationRate*sum;
		if (food - ration < 0){
			return Party.OUT_OF_FOOD;
		}
		else if (totalDistance + pace >= 1909){
			return Party.REACHED_DEST;
		}
		else {
			totalDistance += pace;
			food -= ration;
			//party.setFood(foodLeft);	
			
			//TODO: How do we handle checkpoints?
			if (totalDistance >= checkpoints.get(0).getLocation()) {
				return Party.REACHED_CP;
				//TODO: handle checkpoint code here
			}
			
			return Party.OKAY;

		}
	}

	/**
	 * Sets the party's current ration serving
	 * @param rations The ration setting to be changed to
	 * @return Whether the operation was successful or not
	 */
	public boolean setRations(int rations) {
		this.rations = rations;
		return true;
	}

	/**
	 * Gets and returns the list of party members
	 * @return The list of party members
	 */
	public List<PartyMember> getParty() {
		return party;
	}

	/**
	 * Sets the party member list
	 * @param party The list of party members to be set to
	 */
	public void setParty(List<PartyMember> party) {
		this.party = party;
	}

	/**
	 * Gets and returns the number clothes of the party
	 * @return The number of clothes 
	 */
	public int getClothes() {
		return clothes;
	}

	/**
	 * Sets the clothes of the party
	 * @param clothes The new value of clothes for the party
	 */
	public void setClothes(int clothes) {
		this.clothes = clothes;
	}

	/**
	 * Gets and returns the number of food in the party
	 * @return The number of food in the party
	 */
	public int getFood() {
		return food;
	}

	/**
	 * Sets the number of food for the party
	 * @param food The new number of food for the party 
	 */
	public void setFood(int food) {
		this.food = food;
	}

	/**
	 * Gets and returns the number of ammo for the party
	 * @return The number of ammo for the party
	 */
	public int getAmmo() {
		return ammo;
	}

	/**
	 * Sets the number of ammo for the party
	 * @param ammo The new number of ammo for the party
	 */
	public void setAmmo(int ammo) {
		this.ammo = ammo;
	}

	/**
	 * Gets and returns the wheels for the party
	 * @return The number of wheels for the party
	 */
	public int getWheels(){
		return wheels;
	}
	
	/**
	 * Sets the number of wheels for the party
	 * @param wheels The new number of wheels for the party
	 */
	public void setWheels(int wheels){
		this.wheels = wheels;
	}
	
	/**
	 * Gets and returns the number of axles for the party
	 * @return The number of axles for the party
	 */
	public int getAxels(){
		return axels;
	}
	
	/**
	 * Sets the number of axels for the party
	 * @param axels The new number of axels for the party
	 */
	public void setAxels(int axels){
		this.axels = axels;
	}
	
	/**
	 * Gets and returns the number of tongues for the party
	 * @return The number of tongues for the party
	 */
	public int getTongue(){
		return tongues;
	}
	
	/**
	 * Sets the number of tongues for the party
	 * @param tongues The new number of tongues for the party
	 */
	public void setTongues(int tongues){
		this.tongues = tongues;
	}
	
	/**
	 * Adds wheels to the party
	 * @param wheels The amount of wheels to be added to the party
	 */
	public void addWheels(int wheels){
		this.wheels += wheels;
		if(this.wheels < 0)
			this.wheels = 0;
	}
	
	/**
	 * Adds axles to the party
	 * @param axels The amount of axles to be added to the party
	 */
	public void addAxels(int axels){
		this.axels += axels;
		if(this.axels < 0)
			this.axels = 0;
	}
	
	/**
	 * Add tongues to the party
	 * @param tongues The amount of tongues to be added to the party
	 */
	public void addTongues(int tongues){
		this.tongues += tongues;
		if(this.tongues < 0)
			this.tongues = 0;
	}
	
	/**
	 * Gets and returns the ration rate for the party
	 * @return The ration rate for the party
	 */
	public int getRations() {
		return rations;
	}

	/**
	 * Gets and returns the pace for the party
	 * @return The pace for the party
	 */
	public int getPace() {
		return pace;
	}
	
	/**
	 * Gets and returns the amount of money for the party
	 * @return The amount of money for the party
	 */
	public int getMoney() {
		return money;
	}
	
	/**
	 * Adds money to the party
	 * @param money The amount of money to be added to the party
	 */
	public void addMoney(int money) {
		this.money += money;
	}
	/**
	 * Sets the new money for the party
	 * @param money The new amount of money to be set
	 */
	public void setMoney(int money){
		this.money = money;
	}
	/**
	 * Gets and returns the wagon for the party
	 * @return The wagon for the party
	 */
	public Wagon getWagon(){
		return wagon;
	}
	
	/**
	 * Sets the wagon to a new Wagon
	 * @param newWag The new wagon to be set to
	 */
	public void setWagon(Wagon newWag) {
		wagon = newWag;
	}
	
	/**
	 * Returns the party's current weight
	 * @return the int value of the weight
	 */
	public int getWeight() {
		return weight;
	}
	
	/**
	 * Increments the party's weight
	 * @param add The value to add
	 */
	public void addWeight(int add) {
		weight += add;
	}
	
	/**
	 * Sets the Party's weight
	 * @param weight Sets a new weight for the party
	 */
	public void setWeight(int weight){
		this.weight = weight;
	}
	/**
	 * Decrements the party's weight
	 * @param subtract The value to subtract
	 */
	public void subtractWeight(int subtract) {
		weight -= subtract;
	}
	
	/**
	 * Gets the max weight allowed by the party
	 * @return The max weight allowed
	 */
	public int getMaxWeight() {
		return MAX_WEIGHT;
	}
	
	/**
	 * Sets the party's current pace
	 * @param pace The pace setting to be changed to
	 * @retuen whether the operation was successful or not
	 */
	public boolean setPace(int pace) {
		this.pace = pace;
		return true;
	}
	
	public void setDistanceLeft(int distanceLeft) {
		this.distanceLeft = distanceLeft;
	}

	public int getDistanceLeft() {
		return distanceLeft;
	}

	public void setTotalDistance(int totalDistance) {
		this.totalDistance = totalDistance;
	}

	public int getTotalDistance() {
		return totalDistance;
	}
	
	public void addTotalDistance(int totalDist) {
		totalDistance += totalDist;
	}
	
	public int getLevel(List<Checkpoint> checkpoints) {
		int returnVal = 0;
		
		for (Checkpoint cur : checkpoints) {
			if (totalDistance <= cur.getLocation()) {
				returnVal = cur.getLevel();
				break;
			}
		}
		
		return returnVal;
	}
	
	/**
	 * Returns a string representation of the party
	 */
	@Override
	public String toString() {
		
		String returnVal = "";
		returnVal += "This is a party.\r\n";
		returnVal += "It has " + (party.size() + 1) + " party members.\r\n";
		returnVal += "The player's name is "+ player.getName() +" who has the " + 
			player.getProfession() +" profession. \r\n";
		returnVal += "The status is "+ player.getStatus() + ".\r\n";
		returnVal += "The health is "+ player.getHealth() + ".\r\n";
		
		for (int i = 0; i < party.size(); i++) {
			returnVal += "This is party member " + i + ": \r\n";
			returnVal += party.get(i).toString();
		}
		
		returnVal+= "The party clothes: " + clothes + ".\r\n";
		returnVal+= "The party food: " + food + ".\r\n";
		returnVal+= "The party ammo: " + ammo + ".\r\n";
		returnVal+= "The party wheels: " + wheels + ".\r\n";
		returnVal+= "The party axels: " + axels + ".\r\n";
		returnVal+= "The party tongues: " + tongues + ".\r\n";
		returnVal+= "The party pace: " + pace + ".\r\n";
		returnVal+= "The party rations: " + rations + ".\r\n";
		returnVal+= "The party money: " + money + ".\r\n";
		returnVal+= "The party's wagon: " + wagon.toString() + ".\r\n";

		return returnVal;
	}
}
